/*
-------------------------------------------------

	Audio.cpp

	Dmitriy Kuzmenko (Dgut)

-------------------------------------------------
*/

#include "Audio.h"
#include "Channel.h"
#include "Sound.h"
#include "OGG.h"

using namespace std;

namespace Autumn
{

Audio::Audio( void ) :
	device			( 0 ),
	context			( 0 ),
	musicChannel	( 0 ),
	musicStream		( 0 ),
	soundEnable		( true ),
	musicEnable		( true )
{
}

Audio::~Audio( void )
{
}

const bool Audio::Init( void )
{
	device = alcOpenDevice( 0 );
	if( !device )
		return false;
	
	context = alcCreateContext( device, 0 );
	if( !context )
		return false;
	
	alcMakeContextCurrent( context );
	
	{
		bool error = false;
		for( int i = 0; i < MAX_CHANNELS; i++ )
			if( !( channels[ i ] = Channel::Create() ) )
				error = true;
		if( error )
			return false;
	}

	if( !( musicChannel = Channel::Create() ) )
		return false;
	
	return true;
}

void Audio::Shutdown( void )
{
	for( map< string, Sound * >::iterator i = sounds.begin(); i != sounds.end(); i++ )
		delete i->second;

	for( map< string, Stream * >::iterator i = streams.begin(); i != streams.end(); i++ )
		delete i->second;

	delete musicChannel;
	
	for( int i = 0; i < MAX_CHANNELS; i++ )
		delete channels[ i ];
		
	alcMakeContextCurrent( 0 );
	alcDestroyContext( context );
	alcCloseDevice( device );
}

void Audio::Frame( void )
{
	if( musicEnable && musicStream )
		musicChannel->Play( musicStream );
}

Channel * const Audio::GetChannel( void )
{
	for( int i = 0; i < MAX_CHANNELS; i++ )
		if( channels[ i ]->IsFree() )
		{
//			channels[ i ]->SetLoop( false );
			return channels[ i ];
		}
	
	return 0;
}

void Audio::StopAll( void )
{
	for( int i = 0; i < MAX_CHANNELS; i++ )
		channels[ i ]->Stop();
}

Sound * const Audio::GetSound( const char * name )
{
	Sound * sound = sounds[ name ];
	if( sound )
		return sound;

	return sounds[ name ] = new Sound( &OGG( name ) );
}

const bool Audio::PlaySound( const Sound * sound )
{
	if( !soundEnable )
		return true;

	Channel * channel = GetChannel();

	if( channel )
	{
		channel->Play( sound );
		return true;
	}

	return false;
}

Stream * const Audio::GetStream( const char * name )
{
	Stream * stream = streams[ name ];
	if( stream )
		return stream;

	return streams[ name ] = new Stream( new OGG( name, true ) );
}

void Audio::PlayStream( Stream * stream )
{
	musicStream = stream;
}

void Audio::PlayStream( const char * name )
{
	PlayStream( GetStream( name ) );
}

void Audio::SoundEnable( bool enable )
{
	soundEnable = enable;
	if( !enable )
		StopAll();
}

const bool Audio::IsSoundEnable( void ) const
{
	return soundEnable;
}

void Audio::MusicEnable( bool enable )
{
	musicEnable = enable;
	if( !enable )
		musicChannel->Stop();
}

const bool Audio::IsMusicEnable( void ) const
{
	return musicEnable;
}

}	// namespace Autumn